package com.hl.payServer.core.aliPay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayFundTransToaccountTransferModel;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import tk.mybatis.mapper.util.StringUtil;

import java.util.Map;

/**
 * @author true
 * @date 2017/11/27 0027
 */
public class AliPay {
    public static final String CHARSET = "utf-8";// 编码字符集。默认 utf-8
    public static final String FORMAT = "json";// 返回格式。默认json
    public static final String OPEN_API_DOMAIN="https://openapi.alipay.com/gateway.do";   // 支付宝openapi域名
    public static final String SIGN_TYPE="RSA2";// 支付宝加密方式
    /**
     * 当面付  扫码支付
     * @param alipayClient
     * @param params
     * @return
     * @throws AlipayApiException
     */
    public static AlipayTradePrecreateResponse qrPay(AlipayClient alipayClient, Map<String, Object> params) throws AlipayApiException {
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":\""+params.get("sendOrder").toString()+"\"," +
                "\"total_amount\":"+params.get("payMoney").toString()+"," +
                "\"subject\":\""+(String)params.get("body")+"\"," +
//                "\"timeout_express\":\"25m\"," +
                "\"qr_code_timeout_express\":\"25m\"" +
                "}");
        request.setNotifyUrl(params.get("payNotifyUrl").toString());
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        return response;
    }

    /**
     * 刷卡支付
     * @param alipayClient
     * @param params
     * @return
     */
    public static AlipayTradePayResponse microPay(AlipayClient alipayClient, Map<String, Object> params) throws AlipayApiException {
        AlipayTradePayRequest tradePayRequest = new AlipayTradePayRequest();
        AlipayTradePayModel model = new AlipayTradePayModel();
        model.setScene("bar_code");
        model.setOutTradeNo(params.get("sendOrder").toString());
        model.setAuthCode(params.get("authCode").toString());
        //订单标题
        model.setSubject(params.get("body").toString());
        model.setTimeoutExpress("25m");//25分钟超时
        model.setTotalAmount(params.get("payMoney").toString());
        tradePayRequest.setBizModel(model);
        return alipayClient.execute(tradePayRequest);
    }

    /**
     * app支付
     * @param alipayClient
     * @param params
     * @return
     * @throws AlipayApiException
     */
    public static AlipayTradeAppPayResponse appPay(AlipayClient alipayClient, Map<String, Object> params) throws AlipayApiException {
        //实例化客户端
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        /*
        该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天
         （1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        注：若为空，则默认为15d。
        */
        model.setTimeoutExpress("25m");
        //订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
        model.setTotalAmount(params.get("payMoney").toString());
        //商品的标题/交易标题/订单标题/订单关键字等。
        model.setSubject(params.get("body").toString());
        //商户网站唯一订单号
        model.setOutTradeNo(params.get("sendOrder").toString());
        request.setBizModel(model);
        request.setNotifyUrl(params.get("payNotifyUrl").toString());

        return alipayClient.sdkExecute(request);
    }

    /**
     * 创建支付宝转账给用户request对象
     * @param params
     * @return
     */
    public static AlipayFundTransToaccountTransferRequest createCompanyPayRequest(Map<String, Object> params) {
        AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
        model.setOutBizNo(params.get("outTradeNo").toString());
        model.setPayeeType("ALIPAY_LOGONID");//收款方账户类型。可取值： 1、ALIPAY_USERID：支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。 2、ALIPAY_LOGONID：支付宝登录号，支持邮箱和手机号格式
        model.setPayeeAccount(params.get("openid").toString());//收款方账户
        double amount = Double.parseDouble(params.get("amount").toString())/100;
        model.setAmount(amount+"");//转账金额，单位：元。 只支持2位小数，小数点前最大支持13位，金额必须大于0。
        //model.setPayerRealName(params.get("payerRealName")+"");//可选  付款方真实姓名（最长支持100个英文/50个汉字）。 如果本参数不为空，则会校验该账户在支付宝登记的实名是否与付款方真实姓名一致。
        if (StringUtil.isNotEmpty(params.get("re_user_name")+"")) {
            model.setPayeeRealName(params.get("re_user_name")+"");//可选  收款方真实姓名（最长支持100个英文/50个汉字）。 如果本参数不为空，则会校验该账户在支付宝登记的实名是否与收款方真实姓名一致。
        }
        if (StringUtil.isNotEmpty(params.get("desc")+"")) {
            model.setRemark(params.get("desc")+"");//  转账备注（支持200个英文/100个汉字）。 当付款方为企业账户，且转账金额达到（大于等于）50000元，remark不能为空。收款方可见，会展示在收款用户的账单中。
        }else if(amount >= 50000){
            model.setRemark("转账备注");//转账备注（支持200个英文/100个汉字）。 当付款方为企业账户，且转账金额达到（大于等于）50000元，remark不能为空。收款方可见，会展示在收款用户的账单中。
        }
        AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        request.setBizModel(model);
        return request;
    }

    /**
     * 用于交易创建后，用户在一定时间内未进行支付，可调用该接口直接将未付款的交易进行关闭。
     * 只有等待买家付款状态下才能发起交易关闭
     * @param alipayClient
     * @param params
     * @return
     * @throws AlipayApiException
     *
     * 公共响应参数
     *  参数	类型	是否必填	最大长度	描述	示例值
     *  code	String	是	-	网关返回码,详见文档	40004
        msg	String	是	-	网关返回码描述,详见文档	Business Failed
        sub_code	String	否	-	业务返回码，参见具体的API接口文档	ACQ.TRADE_HAS_SUCCESS
        sub_msg	String	否	-	业务返回码描述，参见具体的API接口文档	交易已被支付
        sign	String	是	-	签名,详见文档	DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo=
     *
     * 公共错误码
     *  ACQ.SYSTEM_ERROR	系统异常	重新发起请求
        ACQ.TRADE_NOT_EXIST	交易不存在	检查传入的交易号和外部订单号是否正确，修改后再重新发起
        ACQ.TRADE_STATUS_ERROR	交易状态不合法	检查当前交易的状态是不是等待买家付付款，只有等待买家付款状态下才能发起交易关闭。
        ACQ.INVALID_PARAMETER	参数无效	检查请求参数，修改后重新发起请求
     */
    public static AlipayTradeCloseResponse close(AlipayClient alipayClient, Map<String, Object> params) throws AlipayApiException {
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        request.setBizContent("{\"out_trade_no\":\""+params.get("outTradeNo").toString()+"\"}");
        return alipayClient.execute(request);
    }

    public static boolean cancel(AlipayClient alipayClient, String outTradeNo)throws AlipayApiException {
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        request.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\"}");
        AlipayTradeCancelResponse response = null;
        response = alipayClient.execute(request);
        return response.isSuccess() && response.getCode().equals("10000") && "N".equals(response.getRetryFlag());
    }

    public static AlipayTradeQueryResponse query(AlipayClient alipayClient, String outTradeNo) throws AlipayApiException {
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\"}");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        return response;
    }
}
